#-*- coding:utf-8 -*-
"""autoRangeLayer by Ozgur Yilmaz and Begum Baskan (c) 2013

v0.1.0

Description :
-------------
Creates attributes for renderLayers, where you can specify frame ranges
that this renderLayer will be rendered. So you can render renderLayers
in different frame ranges. For example, if you need to render one layer
from frame 1 to 10 and another layer from frame 1 to 100 and another one
from frame 40 to 51, normally you need to send different files to render
farm, but with autoRangeLayer you only need to setup and render one
scene

You need to setup the renderLayers by using auto_range_layer_setup_layers, then
set the frame ranges and then add auto_range_layer in the preRenderMEL.

Version History :
-----------------
v0.1.0
- initial working version

TODO List :
-----------
- Add an editor to manage layer attributes

"""

__version__ = '0.1.0'

import pymel.core as pm
import maya.mel as mel


class autoRangeLayer(object):
    @classmethod
    def auto_range_layer(cls):
        if pm.about(b=1):
            renderLayers = pm.ls(type="renderLayer")

            for i in range(0, len(renderLayers)):
                if renderLayers[i].hasattr('renderRangeMin') and renderLayers[i].hasAttr('renderRangeMax'):
                    minRange = renderLayers[i].renderRangeMin.get()
                    maxRange = renderLayers[i].renderRangeMax.get()
                    if renderLayers[i].renderable.get() == 1:
                        frame = pm.getAttr('defaultRenderGlobals.startFrame')
                        if frame < minRange or frame > maxRange:
                            renderLayers[i].renderable.set(0)

    @classmethod
    def auto_range_layer_setup_layers(cls):
        renderLayers = pm.ls(type="renderLayer")

        for i in range(0, len(renderLayers)):
            if renderLayers[i].hasAttr('renderRangeMin') == 0:
                renderLayers[i].addAttr('renderRangeMin', at='long')
                renderLayers[i].renderRangeMin.set(e=True, keyable=True)
        for i in range(0, len(renderLayers)):
            if renderLayers[i].hasAttr('renderRangeMax') == 0:
                renderLayers[i].addAttr('renderRangeMax', at='long')
                renderLayers[i].renderRangeMax.set(e=True, keyable=True)


class Editor():
    def __init__(self):
        self._rangeMin = ""
        self._rangeMax = ""
        self._preRender = ""
        self._postRender = ""
        self._preRenderLayer = ""
        self._postRenderLayer = ""
        self._preRenderFrame = ""
        self._postRenderFrame = ""

        self.rangeMinField = None
        self.rangeMaxField = None
        self.preRenderField = None
        self.postRenderField = None
        self.preRenderLayerField = None
        self.postRenderLayerField = None
        self.preRenderFrameField = None
        self.postRenderFrameField = None
        self.textScrollList = []

    @property
    def rangeMin(self):
        return self._rangeMin

    @rangeMin.setter
    def rangeMin(self, rangeMin):
        self._rangeMin = rangeMin
        if self.rangeMinField:
            self.rangeMinField.text = rangeMin

    @property
    def rangeMax(self):
        return self._rangeMax

    @rangeMax.setter
    def rangeMax(self, rangeMax):
        self._rangeMax = rangeMax
        if self.rangeMaxField:
            self.rangeMaxField.text = rangeMax

    def arl_setup_layers(self):
        currLayer = pm.editRenderLayerGlobals(q=True, currentRenderLayer=True)

        minValue = int(pm.textFieldGrp(self.rangeMinField, q=True, tx=True))
        maxValue = int(pm.textFieldGrp(self.rangeMaxField, q=True, tx=True))
        pm.setAttr('%s.renderRangeMin' % currLayer, minValue)
        pm.setAttr('%s.renderRangeMax' % currLayer, maxValue)

    #----- PRE RENDER MEL -----
    @property
    def preRender(self):
        return self._preRender

    @preRender.setter
    def preRender(self, preRender):
        self._preRender = preRender
        if self.preRenderField:
            self.preRenderField.text = preRender

    def preRenderSetting(self):
        preMel = pm.textFieldButtonGrp(self.preRenderField, q=True, tx=True)
        pm.setAttr("defaultRenderGlobals.preMel", preMel)

    #----- POST RENDER MEL -----
    @property
    def postRender(self):
        return self._postRender

    @postRender.setter
    def postRender(self, postRender):
        self._postRender = postRender
        if self.postRenderField:
            self.postRenderField.text = postRender

    def postRenderSetting(self):
        postMel = pm.textFieldButtonGrp(self.postRenderField, q=True, tx=True)
        pm.setAttr("defaultRenderGlobals.postMel", postMel)

    #----- PRE RENDER LAYER MEL -----
    @property
    def preRenderLayer(self):
        return self._preRenderLayer

    @preRenderLayer.setter
    def preRenderLayer(self, preRenderLayer):
        self._preRenderLayer = preRenderLayer
        if self.preRenderLayerField:
            self.preRenderLayerField.text = preRenderLayer

    def preRenderLayerSetting(self):
        preLayerMel = pm.textFieldButtonGrp(self.preRenderLayerField, q=True, tx=True)
        pm.setAttr("defaultRenderGlobals.preRenderLayerMel", preLayerMel)

    #----- POST RENDER LAYER MEL -----
    @property
    def postRenderLayer(self):
        return self._postRenderLayer

    @postRenderLayer.setter
    def postRenderLayer(self, postRenderLayer):
        self._postRenderLayer = postRenderLayer
        if self.postRenderLayerField:
            self.postRenderLayerField.text = postRenderLayer

    def postRenderLayerSetting(self):
        postLayerMel = pm.textFieldButtonGrp(self.postRenderLayerField, q=True, tx=True)
        pm.setAttr("defaultRenderGlobals.postRenderLayerMel", postLayerMel)
        self.preRenderSetting()

    #----- PRE RENDER FRAME MEL -----
    @property
    def preRenderFrame(self):
        return self._preRenderFrame

    @preRenderFrame.setter
    def preRenderFrame(self, preRenderFrame):
        self._preRenderFrame = preRenderFrame
        if self.preRenderFrameField:
            self.preRenderFrameField.text = preRenderFrame

    def preRenderFrameSetting(self):
        preFrameMel = pm.textFieldButtonGrp(self.preRenderFrameField, q=True, tx=True)
        pm.setAttr("defaultRenderGlobals.preRenderMel", preFrameMel)

    #----- POST RENDER FRAME MEL -----
    @property
    def postRenderFrame(self):
        return self._postRenderFrame

    @postRenderFrame.setter
    def postRenderFrame(self, postRenderFrame):
        self._postRenderFrame = postRenderFrame
        if self.postRenderFrameField:
            self.postRenderFrameField.text = postRenderFrame

    def postRenderFrameSetting(self):
        postFrameMel = pm.textFieldButtonGrp(self.postRenderFrameField, q=True, tx=True)
        pm.setAttr("defaultRenderGlobals.postRenderMel", postFrameMel)

    def refreshLayers(self):
        renderLayers = pm.ls(type='renderLayer')
        selectedRender = pm.editRenderLayerGlobals(q=True, currentRenderLayer=True)
        numberOfItems = pm.textScrollList(self.textScrollList, q=True, ni=True)
        numberOfRenderLayers = len(renderLayers)
        oldItems = pm.textScrollList(self.textScrollList, q=True, allItems=True)
        if numberOfItems == numberOfRenderLayers:
            for i in range(0, numberOfRenderLayers):
                if not renderLayers[i] in oldItems:
                    pm.textScrollList(self.textScrollList, edit=True,
                                      append='%s' % renderLayers[i])
                    self.refreshLayers()
        elif numberOfItems > numberOfRenderLayers:
            for i in range(0, numberOfItems):
                if not oldItems[i] in renderLayers:
                    pm.textScrollList(self.textScrollList, edit=True, ri='%s' % oldItems[i])
        elif numberOfItems < numberOfRenderLayers:
            for i in range(0, numberOfRenderLayers):
                if not renderLayers[i] in oldItems:
                    pm.textScrollList(self.textScrollList, edit=True, append='%s' % renderLayers[i])

        pm.textScrollList(self.textScrollList, edit=True, selectItem=selectedRender)

    def emptyRenderMELFields(self):
        pm.setAttr("defaultRenderGlobals.preMel", "")
        pm.setAttr("defaultRenderGlobals.postMel", "")
        pm.setAttr("defaultRenderGlobals.preRenderLayerMel", "")
        pm.setAttr("defaultRenderGlobals.postRenderLayerMel", "")
        pm.setAttr("defaultRenderGlobals.preRenderMel", "")
        pm.setAttr("defaultRenderGlobals.postRenderMel", "")
        self._preRender = ""
        pm.textFieldButtonGrp(self.preRenderField, edit=True, text=self.preRender)
        self._postRender = ""
        pm.textFieldButtonGrp(self.postRenderField, edit=True, text=self.postRender)
        self._preRenderLayer = ""
        pm.textFieldButtonGrp(self.preRenderLayerField, edit=True, text=self.preRenderLayer)
        self._postRenderLayer = ""
        pm.textFieldButtonGrp(self.postRenderLayerField, edit=True, text=self.postRenderLayer)
        self._preRenderFrame = ""
        pm.textFieldButtonGrp(self.preRenderFrameField, edit=True, text=self.preRenderFrame)
        self._postRenderFrame = ""
        pm.textFieldButtonGrp(self.postRenderFrameField, edit=True, text=self.postRenderFrame)

    def makeCurrentLayer(self):
        selectedLayer = pm.textScrollList("textScrollList", q=True, selectItem=True)[0]
        pm.editRenderLayerGlobals(currentRenderLayer=selectedLayer)

    def add_autoRangeLayer(self):
        self._preRender = "python(\"autoRangeLayer.auto_range_layer()\");"
        pm.textFieldButtonGrp(self.preRenderField, edit=True, text=self.preRender)
        self.preRenderSetting()

    def UI(self):
        autoRangeLayer.auto_range_layer_setup_layers()

        if pm.window("autoRangeLayer_Window", ex=True):
            pm.deleteUI("autoRangeLayer_Window", wnd=True)

        autoRangeLayer_Window = pm.window('autoRangeLayer_Window', wh=(500, 600),
                                          title=("autoRangeLayer " + __version__))
        with autoRangeLayer_Window:
            formLayout = pm.formLayout('autoRangeLayer_formLayout', nd=100)
            with formLayout:
                pm.frameLayout(label='Render Layers', borderStyle='out', w=500)

                self.textScrollList = pm.textScrollList("textScrollList", allowMultiSelection=False,
                                                        showIndexedItem=5, sc=pm.Callback(self.makeCurrentLayer))
                renderLayers = pm.ls(type='renderLayer')
                selectedRender = pm.editRenderLayerGlobals(q=True, currentRenderLayer=True)
                for i in range(0, len(renderLayers)):
                    pm.textScrollList("textScrollList", edit=True, append='%s' % renderLayers[i])
                pm.textScrollList("textScrollList", edit=True, selectItem=selectedRender)

                pm.textScrollList(self.textScrollList, edit=True)
                pm.rowColumnLayout(numberOfColumns=1, columnWidth=[(1, 497)])
                pm.button(ann="refresh the render layer List", l="Refresh",
                          c=pm.Callback(self.refreshLayers))
                pm.rowColumnLayout(numberOfColumns=2, columnWidth=[(1, 247), (2, 247)])
                pm.button(ann="open Attribute Editor",
                          label="Attribute Editor",
                          c=pm.Callback(mel.eval, 'renderLayerEditorLayerAttributes("")'))

                pm.button(ann="open Render Settings",
                          label="Render Settings",
                          c=pm.Callback(mel.eval, 'unifiedRenderGlobalsWindow()'))

                pm.frameLayout(label='Render Range', borderStyle='out', w=500)
                pm.attrControlGrp(attribute="defaultRenderLayer.isDefaultPrecompTemplateOverride")
                self.rangeMinField = pm.textFieldGrp(text=self.rangeMin, label="Render Range Min", w=300)
                self.rangeMaxField = pm.textFieldGrp(text=self.rangeMax, label="Render Range Max", w=300)
                pm.rowColumnLayout(numberOfColumns=1, columnWidth=[(1, 497)])
                pm.button(ann="set Range Values", l="Set Range Values",
                          c=pm.Callback(self.arl_setup_layers))

                pm.frameLayout(label='Render MEL', borderStyle='out', w=500)
                self.preRenderField = pm.textFieldButtonGrp(text=self.preRender,
                                                            l="Pre Render MEL",
                                                            bl="   Set   ",
                                                            bc=pm.Callback(self.preRenderSetting),
                                                            adj=2, tx="", cat=(1, "right", 3), cw=(1, 123))
                self.postRenderField = pm.textFieldButtonGrp(text=self.postRender,
                                                             l="Post Render MEL",
                                                             bl="   Set   ",
                                                             bc=pm.Callback(self.postRenderSetting),
                                                             adj=2, tx="", cat=(1, "right", 3), cw=(1, 123))

                self.preRenderLayerField = pm.textFieldButtonGrp(text=self.preRenderLayer,
                                                                 l="Pre Render Layer MEL",
                                                                 bl="   Set   ",
                                                                 bc=pm.Callback(self.preRenderLayerSetting),
                                                                 adj=2, tx="", cat=(1, "right", 3), cw=(1, 123))
                self.postRenderLayerField = pm.textFieldButtonGrp(text=self.postRenderLayer,
                                                                  l="Post Render Layer MEL",
                                                                  bl="   Set   ",
                                                                  bc=pm.Callback(self.postRenderLayerSetting),
                                                                  adj=2, tx="", cat=(1, "right", 3), cw=(1, 123))

                self.preRenderFrameField = pm.textFieldButtonGrp(text=self.preRenderFrame,
                                                                 l="Pre Render Frame MEL",
                                                                 bl="   Set   ",
                                                                 bc=pm.Callback(self.preRenderFrameSetting),
                                                                 adj=2, tx="", cat=(1, "right", 3), cw=(1, 123))
                self.postRenderFrameField = pm.textFieldButtonGrp(text=self.postRender,
                                                                  l="Post Render Frame MEL",
                                                                  bl="   Set   ",
                                                                  bc=pm.Callback(self.postRenderFrameSetting),
                                                                  adj=2, tx="", cat=(1, "right", 3), cw=(1, 123))

                pm.attrControlGrp(attribute="defaultRenderGlobals.enableDefaultLight")
                pm.rowColumnLayout(numberOfColumns=2, columnWidth=[(1, 247), (2, 247)])
                pm.button(ann="add auto_range_layer in the preRenderMEL",
                          label="autoRangeLayer",
                          c=pm.Callback(self.add_autoRangeLayer))
                pm.button(ann="Empty Render MEL Fields",
                          label="Empty Fields",
                          c=pm.Callback(self.emptyRenderMELFields))

        pm.showWindow(autoRangeLayer_Window)